package com.hopes.bizz.common.core.util;

/**
 * @author daijie
 * @version 1.0
 * @date 2023/5/19 11:10
 * @Description: crc算法帮助类
 */
public class CRCUtils {

    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};


    /**
     * 获取crc16校验码
     *
     * @param data
     * @return
     */
    public static String getCRC16(String data) {
        int crc = 0xFFFF;
        byte[] datas = data.getBytes();
        int check;
        int i, j;
        for (i = 0; i < datas.length; i++) {
            crc = (crc >> 8) ^ datas[i];
            for (j = 0; j < 8; j++) {
                check = crc & 0x0001;
                crc >>= 1;
                if (check == 0x0001) {
                    crc ^= 0xA001;
                }
            }
        }
        String tempCRC = Integer.toHexString(crc).toUpperCase();
        int length = tempCRC.length();
        if (length < 4) {
            for (int zero = 4 - length; zero > 0; zero--) {
                tempCRC = "0" + tempCRC;
            }
        }
        return tempCRC;
    }

    /**
     * 计算CRC16校验码
     *
     * @param bytes
     * @return
     */
    public static String getCRC(Byte[] bytes) {
        return getCRC(bytes, false);
    }

    /**
     * 计算CRC16校验码
     *
     * @param bytes
     * @return
     */
    public static String getCRC(Byte[] bytes, boolean highFirst) {
        int CRC = 0x0000ffff;
        int POLYNOMIAL = 0x0000a001;

        int i, j;
        for (i = 0; i < bytes.length; i++) {
            CRC ^= ((int) bytes[i] & 0x000000ff);
            for (j = 0; j < 8; j++) {
                if ((CRC & 0x00000001) != 0) {
                    CRC >>= 1;
                    CRC ^= POLYNOMIAL;
                } else {
                    CRC >>= 1;
                }
            }
        }
        if (highFirst) {
            byte[] tempBytes = new byte[2];
            tempBytes[0] = (byte) (CRC & 0xff);
            tempBytes[1] = (byte) ((CRC >> 8) & 0xff);
            char[] buf = new char[tempBytes.length * 2];
            int index = 0;
            for (byte b : tempBytes) { // 利用位运算进行转换，可以看作方法一的变种
                buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
                buf[index++] = HEX_CHAR[b & 0xf];
            }
            return new String(buf);
        }
        return Integer.toHexString(CRC).toUpperCase();
    }


    public static void main(String[] args) {
//        byte[]  bytes = new byte[]{0x37,0x03,0x0,0x0,0x0,0x1};
        Byte[] bytes = new Byte[]{0x37, 0x03, 0x00, 0x00, 0x00, 0x02};

//        Integer crc = CRC16.calc(bytes);
//        System.out.println(Integer.toHexString(crc));
//        System.out.println(NumberUitl.getHex(NumberUitl.get2Bytes(crc)));
        String crcCode = getCRC(bytes, true);
        System.out.println(crcCode);
    }
}
